var paperWidth = 1200;
var paperHeight = 800;
var paperOffset = 400;
////*************************************以上为全局变量*******************************************///
//oldId->newId
var idMap = new Map();
var nodeMap = new Map();
// 外部系统用的主graph
var graph = new joint.dia.Graph;
// 外部系统用的主paper
var paper = new joint.dia.Paper({
	el : $('#paper'),
	width : paperWidth,
	height : paperHeight,
	gridSize : 1,
	model : graph
});
//paper画布所在div
var paperDiv = $("#paper");
paperDiv.height(paperHeight);
paperDiv.width(paperWidth);
graph.on('change', function(cell) { 
	return;
});
var createNode = function(xP, yP,height,width, name, image,inports,outports) {
	var node = new joint.shapes.devs.Atomic({
		position : {
			x : xP,
			y : yP
		},
		size : {
			width : width,
			height : height
		},
		attrs : {
			image : {
				'xlink:href' : 'img/aadl/' + image
			},
			'.label' : {
				text : name
			}
		},
		inPorts : inports,
		outPorts : outports
	});
	graph.addCell(node);
	return node;
};

var createCoupled = function(xP, yP, name,width,height,inports,outports) {
	var node = new joint.shapes.devs.Coupled({
		position : {
			x : xP,
			y : yP
		},
		attrs : {
			'.label' : {
				text : name
			}
		},
		size : {
			width : width,
			height : height
		},
		inPorts : inports,
		outPorts : outports
	});
	graph.addCell(node);
	return node;
};
function getPortTypePre(type) {
	switch (type) {
	case "In Data Port":
		return "In Data:";
	case "Out Data Port":
		return "Out Data:";
	case "InOut Data Port":
		return "InOut Data:";
	case "In Event Port":
		return "In Event:";
	case "Out Event Port":
		return "Out Event:";
	case "InOut Event Port":
		return "InOut Event:";
	case "In DataEvent Port":
		return "In DataEvent:";
	case "Out DataEvent Port":
		return "Out DataEvent:";
	case "InOut DataEvent Port":
		return "InOut DataEvent:";
	case "Requires Data Access":
		return "Requires Data:";
	case "Provides Data Access":
		return "Provides Data:";
	case "Requires Bus Access":
		return "Requires Bus:";
	case "Provides Bus Access":
		return "Provides Bus:";
	}
}
//link source的sourcePort至target的targetPort
var connect = function(source, sourcePort, target, targetPort) {
	var link = null;
	if(sourcePort != null){
		if(targetPort != null){
			link = new joint.shapes.devs.Link({
				source : {
					id : source.id,
					selector : source.getPortSelector(sourcePort)
				},
				target : {
					id : target.id,
					selector : target.getPortSelector(targetPort)
				}
			});
		}else{
				link = new joint.shapes.devs.Link({
					source : {
						id : source.id,
						selector : source.getPortSelector(sourcePort)
					},
					target : {
						id : target.id
					}
				});
		}
	}else{
		if(targetPort != null){
			link = new joint.shapes.devs.Link({
				source : {
					id : source.id
				},
				target : {
					id : target.id,
					selector : target.getPortSelector(targetPort)
				}
			});
		}else{
				link = new joint.shapes.devs.Link({
					source : {
						id : source.id
					},
					target : {
						id : target.id
					}
				});
		}
	}
	graph.addCell(link);
	//return link;
};
function getPortTypeDirection(type) {
	switch (type) {
	case "In Data Port":
	case "InOut Data Port":
	case "In Event Port":
	case "InOut Event Port":
	case "In DataEvent Port":
	case "InOut DataEvent Port":
	case "Requires Data Access":
	case "Requires Bus Access":
		return "in";
	case "Out Data Port":
	case "Out Event Port":
	case "Out DataEvent Port":
	case "Provides Data Access":
	case "Provides Bus Access":
		return "out";
	}
}
var parent;
function parseNode(nodeJson){
	var size = nodeJson.length;
	for(var i= 0;i<size;i++){
		var inports = new Array();
		var outports = new Array();
		if(nodeJson[i].features != null){
			var port_size = nodeJson[i].features.length;
			for(var j=0;j<port_size;j++){
				var name = nodeJson[i].features[j].name;
				var type = parseFeatureType(nodeJson[i].features[j].type);
				var port = getPortTypePre(type)+name;
				var direction = getPortTypeDirection(type);
				if(direction == "in"){
					inports.push(port);
				}else{
					outports.push(port);
				}
			}
		}
		if(!nodeJson[i].hasChild){
			var node = createNode(nodeJson[i].x, nodeJson[i].y,nodeJson[i].height,nodeJson[i].width, nodeJson[i].name, nodeJson[i].type+"_large.png",inports,outports);
			nodeMap.put(node.id,node);
			idMap.put(nodeJson[i].id,node.id);
		}else{
			//重新设置高度，添加内嵌图
			paperHeight = paperHeight+paperOffset;
			paper.setDimensions(paperWidth, paperHeight);
			paperDiv.height(paperHeight+20);
			var node = createCoupled(nodeJson[i].x, nodeJson[i].y, nodeJson[i].name,nodeJson[i].width,nodeJson[i].height,inports,outports);
			nodeMap.put(node.id,node);
			idMap.put(nodeJson[i].id,node.id);
		}
		
	}
	for(var i= 0;i<size;i++){
		var parentId= nodeJson[i].parent_id;
		var id = nodeJson[i].id;
		if(parentId != null){
			parent = nodeMap.get(idMap.get(parentId));
			child = nodeMap.get(idMap.get(id));
			
			if(parent != null && parent.attributes.type == "devs.Coupled"){
				parent.embed(child);
			}
		}
		
	}
}

function parseFeatureType(aadlType){
	switch(aadlType){
		case"in data port":
			return "In Data Port";
		case "out data port":
			return "Out Data Port";
		case "in out data port":
			return "InOut Data Port";
		case "in event port":
			return "In Event Port";
		case "out event port":
			return "Out Event Port";
		case "in out event port":
			return "InOut Event Port";
		case "in event data port":
			return "In DataEvent Port";
		case "out event data port":
			return "Out DataEvent Port";
		case "in out event data port":
			return "InOut DataEvent Port";
		case "requires data access":
			return "Requires Data Access";
		case "provides data access":
			return "Provides Data Access";
		case "requires bus access":
			return "Requires Bus Access";
		case "provides bus access":
			return "Provides Bus Access";
	}
	return "";
}
function parsePaper(width,height){
	paperWidth = width;
	paperHeight = height;
	paper.setDimensions(paperWidth, paperHeight);
	paperDiv.height(paperHeight+500);
}
function parseLink(linkJson){
	var size = linkJson.length;
	for(var i= 0;i<size;i++){
		var sourceId = linkJson[i].sourceId;
		var sourcePort = (linkJson[i].sourcePort=="null"||linkJson[i].sourcePort=="")?null:linkJson[i].sourcePort;
		var targetId = linkJson[i].targetId;
		var targetPort = (linkJson[i].targetPort=="null"||linkJson[i].targetPort=="")?null:linkJson[i].targetPort;
		connect(nodeMap.get(idMap.get(sourceId)), sourcePort, nodeMap.get(idMap.get(targetId)), targetPort);
	}
}